﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using 设计模块.Observer;
using 设计模块.Strategy;
using 设计模块.TemplateMethod;
using 设计模块.Visitor;
using 设计模式.Command;
using 设计模式.Bridge;
using 设计模式.Singleton;
using 设计模式.Decorator;
using 设计模式.Adapter;
using System.Xml.Serialization;
using System.IO;
using System.Xml;
using System.Reflection;
using System.Reflection.Emit;
using System.Diagnostics;
using System.Threading;
namespace 设计模块
{

    public class User_Info
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public bool IsDel { get; set; }
    }
    class Program
    {

        static void Main(string[] args)
        {
            #region 策略
            // Three contexts following different strategies
            Context c = new Context(new ConcreteStrategyA());
            c.ContextInterface();
            #endregion

            #region 访问者
            // Setup employee collection
            Employees e = new Employees();
            e.Attach(new Employee("Hank", 25000.0, 14));
            e.Attach(new Employee("Elly", 35000.0, 16));
            e.Attach(new Employee("Dick", 45000.0, 21));

            // Create two visitors
            IncomeVisitor v1 = new IncomeVisitor();
            VacationVisitor v2 = new VacationVisitor();

            // Employees are visited
            e.Accept(v1);
            e.Accept(v2);
            #endregion

            #region 观察者
            ConcreteSubject s = new ConcreteSubject();
            s.Attach(new ConcreteObserver(s, "1"));
            s.Attach(new ConcreteObserver(s, "2"));
            s.Attach(new ConcreteObserver(s, "3"));
            // Change subject and notify observers
            s.SubjectState = "ABC";
            s.Notify();
            #endregion

            #region 模板方法
            AbstractClass cc = new ChinaClass();
            cc.OrderFinish();
            cc = new USAClass();
            cc.OrderFinish();
            #endregion

            #region 命令模式
            // Create receiver, command, and invoker
            Receiver r = new Receiver();
            Command ccc = new ConcreteCommand(r);
            Invoker i = new Invoker();
            // Set and execute command
            i.SetCommand(ccc);
            i.ExecuteCommand();
            #endregion

            #region 桥接模式
            Abstraction abstraction = new RefinedAbstraction();

            // Set implementation and call
            abstraction.Implementor = new ConcreteImplementorA();
            abstraction.Operation();

            // Change implemention and call
            abstraction.Implementor = new ConcreteImplementorB();
            abstraction.Operation();
            #endregion

            #region 单例模块

            Singleton.Instance.Add("zzl");
            Singleton.Instance.Add("lr");
            Singleton.Instance.StrContext.ForEach(ii => Console.WriteLine(ii));
            #endregion

            #region 装饰模式
            Log log;
            log = new DatabaseLog();
            log.Write("ok");

            log = new TextFileLog();
            log.Write("hehe");

            new DomainTest(new TestEventHandle()).Process("process domain event.");

            new DomainTest(new DomainDelegate((msg) =>
            {
                Console.WriteLine("这个方法可以自己去定义，对外都是Process，只是生成IEvent的方式不同，将Action<string>装饰成了IEvent的方法");
            })).Process("process domain event.");

            #endregion

            #region 适配器模式
            IStandard iStandard = new Target();
            iStandard.ResponseDo("ok");

            iStandard = new Adapter();
            iStandard.ResponseDo("OK特殊");
            #endregion

            Class1 c1 = new Class1 { IntValue = 3, StrValue = "Fish Li" };
            string xml = XmlHelper.XmlSerialize(c1, Encoding.UTF8);
            Console.WriteLine(xml);
            Console.WriteLine("---------------------------------------");
            Class1 c2 = XmlHelper.XmlDeserialize<Class1>(xml, Encoding.UTF8);
            Console.WriteLine("IntValue: " + c2.IntValue.ToString());
            Console.WriteLine("StrValue: " + c2.StrValue);

            Class2 c21 = new Class2 { IntValue = 3, StrValue = "Fish Li" };
            string xml2 = XmlHelper.XmlSerialize(c21, Encoding.UTF8);
            Console.WriteLine(xml2);
            Console.WriteLine("---------------------------------------");
            Class2 c22 = XmlHelper.XmlDeserialize<Class2>(xml2, Encoding.UTF8);
            Console.WriteLine("IntValue: " + c21.IntValue.ToString());
            Console.WriteLine("StrValue: " + c21.StrValue);

            Class3 c31 = new Class3
            {
                IntValue = 3,
                StrValue = "Fish Li"
            };
            string xml3 = XmlHelper.XmlSerialize(c31, Encoding.UTF8);
            Console.WriteLine(xml3);
            Console.WriteLine("---------------------------------------");
            Class3 c32 = XmlHelper.XmlDeserialize<Class3>(xml3, Encoding.UTF8);
            Console.WriteLine("IntValue: " + c32.IntValue.ToString());
            Console.WriteLine("StrValue: " + c32.StrValue);


            Class1 c41 = new Class1
            {
                IntValue = 3,
                StrValue = "Fish Li"
            };
            Class1 c42 = new Class1
            {
                IntValue = 4,
                StrValue = "http://www.cnblogs.com/fish-li/"
            };

            // 说明：下面二行代码的输出结果是一样的。
            Roots rr = new Roots();
            rr.list = new List<Class1> { c1, c2 };
            string xml4 = XmlHelper.XmlSerialize(rr, Encoding.UTF8);
            Console.WriteLine(xml4);


            Console.WriteLine(System.Runtime.InteropServices.RuntimeEnvironment.GetSystemVersion());

            int count = 1000000;

            OrderInfo testObj = new OrderInfo();
            PropertyInfo propInfo = typeof(OrderInfo).GetProperty("OrderID");

            Console.Write("直接访问花费时间：       ");
            Stopwatch watch1 = Stopwatch.StartNew();

            for (int ii = 0; ii < count; ii++)
                testObj.OrderID = 123;

            watch1.Stop();
            Console.WriteLine(watch1.Elapsed.ToString());


            SetValueDelegate setter2 = DynamicMethodFactory.CreatePropertySetter(propInfo);
            Console.Write("EmitSet花费时间：        ");
            Stopwatch watch2 = Stopwatch.StartNew();

            for (int ii = 0; ii < count; ii++)
                setter2(testObj, 123);

            watch2.Stop();
            Console.WriteLine(watch2.Elapsed.ToString());


            Console.Write("纯反射花费时间：　       ");
            Stopwatch watch3 = Stopwatch.StartNew();

            for (int ii = 0; ii < count; ii++)
                propInfo.SetValue(testObj, 123, null);

            watch3.Stop();
            Console.WriteLine(watch3.Elapsed.ToString());


            Console.WriteLine("-------------------");
            Console.WriteLine("{0} / {1} = {2}",
                watch3.Elapsed.ToString(),
                watch1.Elapsed.ToString(),
                watch3.Elapsed.TotalMilliseconds / watch1.Elapsed.TotalMilliseconds);

            Console.WriteLine("{0} / {1} = {2}",
                watch3.Elapsed.ToString(),
                watch2.Elapsed.ToString(),
                watch3.Elapsed.TotalMilliseconds / watch2.Elapsed.TotalMilliseconds);

            Console.WriteLine("{0} / {1} = {2}",
                watch2.Elapsed.ToString(),
                watch1.Elapsed.ToString(),
                watch2.Elapsed.TotalMilliseconds / watch1.Elapsed.TotalMilliseconds);


            int a = 0;

            object lockObj = new object();
            Task.Run(() =>
            {
                Monitor.Enter(lockObj);
                a = 1;
                Monitor.Exit(lockObj);
            }).Wait();
            Console.WriteLine(a);


            new Bulk<User_Info>().BulkInsert(new List<User_Info>());

            Console.ReadKey();
        }
    }
    public class Bulk<T> where T : class
    {
        public void BulkInsert(List<T> list)
        {
            List<string> propertyNameList = new List<string>();
            var param = typeof(T).GetProperties();
            foreach (var item in param)
            {
                propertyNameList.Add(item.Name);
            }
              
            propertyNameList.ForEach(i => Console.WriteLine(i));
        }
    }
    public class Class1
    {
        public int IntValue { get; set; }

        public string StrValue { get; set; }
    }
    public class Class2
    {
        [XmlAttribute]
        public int IntValue { get; set; }

        [XmlElement]
        public string StrValue { get; set; }
    }
    public class Class3
    {
        [XmlAttribute]
        public int IntValue { get; set; }

        [XmlText]
        public string StrValue { get; set; }
    }
    public class Roots
    {
        public List<Class1> list { get; set; }
    }
    public static class XmlHelper
    {
        private static void XmlSerializeInternal(Stream stream, object o, Encoding encoding)
        {
            if (o == null)
                throw new ArgumentNullException("o");
            if (encoding == null)
                throw new ArgumentNullException("encoding");

            XmlSerializer serializer = new XmlSerializer(o.GetType());

            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            settings.NewLineChars = "\r\n";
            settings.Encoding = encoding;
            settings.IndentChars = "    ";

            using (XmlWriter writer = XmlWriter.Create(stream, settings))
            {
                serializer.Serialize(writer, o);
                writer.Close();
            }
        }

        /// <summary>
        /// 将一个对象序列化为XML字符串
        /// </summary>
        /// <param name="o">要序列化的对象</param>
        /// <param name="encoding">编码方式</param>
        /// <returns>序列化产生的XML字符串</returns>
        public static string XmlSerialize(object o, Encoding encoding)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                XmlSerializeInternal(stream, o, encoding);

                stream.Position = 0;
                using (StreamReader reader = new StreamReader(stream, encoding))
                {
                    return reader.ReadToEnd();
                }
            }
        }

        /// <summary>
        /// 将一个对象按XML序列化的方式写入到一个文件
        /// </summary>
        /// <param name="o">要序列化的对象</param>
        /// <param name="path">保存文件路径</param>
        /// <param name="encoding">编码方式</param>
        public static void XmlSerializeToFile(object o, string path, Encoding encoding)
        {
            if (string.IsNullOrEmpty(path))
                throw new ArgumentNullException("path");

            using (FileStream file = new FileStream(path, FileMode.Create, FileAccess.Write))
            {
                XmlSerializeInternal(file, o, encoding);
            }
        }

        /// <summary>
        /// 从XML字符串中反序列化对象
        /// </summary>
        /// <typeparam name="T">结果对象类型</typeparam>
        /// <param name="s">包含对象的XML字符串</param>
        /// <param name="encoding">编码方式</param>
        /// <returns>反序列化得到的对象</returns>
        public static T XmlDeserialize<T>(string s, Encoding encoding)
        {
            if (string.IsNullOrEmpty(s))
                throw new ArgumentNullException("s");
            if (encoding == null)
                throw new ArgumentNullException("encoding");

            XmlSerializer mySerializer = new XmlSerializer(typeof(T));
            using (MemoryStream ms = new MemoryStream(encoding.GetBytes(s)))
            {
                using (StreamReader sr = new StreamReader(ms, encoding))
                {
                    return (T)mySerializer.Deserialize(sr);
                }
            }
        }

        /// <summary>
        /// 读入一个文件，并按XML的方式反序列化对象。
        /// </summary>
        /// <typeparam name="T">结果对象类型</typeparam>
        /// <param name="path">文件路径</param>
        /// <param name="encoding">编码方式</param>
        /// <returns>反序列化得到的对象</returns>
        public static T XmlDeserializeFromFile<T>(string path, Encoding encoding)
        {
            if (string.IsNullOrEmpty(path))
                throw new ArgumentNullException("path");
            if (encoding == null)
                throw new ArgumentNullException("encoding");

            string xml = File.ReadAllText(path, encoding);
            return XmlDeserialize<T>(xml, encoding);
        }
    }


    public delegate void SetValueDelegate(object target, object arg);

    public class OrderInfo
    {
        public int OrderID { get; set; }
    }
    public static class DynamicMethodFactory
    {
        public static SetValueDelegate CreatePropertySetter(PropertyInfo property)
        {
            if (property == null)
                throw new ArgumentNullException("property");

            if (!property.CanWrite)
                return null;

            MethodInfo setMethod = property.GetSetMethod(true);

            DynamicMethod dm = new DynamicMethod("PropertySetter", null,
                new Type[] { typeof(object), typeof(object) },
                property.DeclaringType, true);

            ILGenerator il = dm.GetILGenerator();

            if (!setMethod.IsStatic)
            {
                il.Emit(OpCodes.Ldarg_0);
            }
            il.Emit(OpCodes.Ldarg_1);

            EmitCastToReference(il, property.PropertyType);
            if (!setMethod.IsStatic && !property.DeclaringType.IsValueType)
            {
                il.EmitCall(OpCodes.Callvirt, setMethod, null);
            }
            else
                il.EmitCall(OpCodes.Call, setMethod, null);

            il.Emit(OpCodes.Ret);

            return (SetValueDelegate)dm.CreateDelegate(typeof(SetValueDelegate));
        }

        private static void EmitCastToReference(ILGenerator il, Type type)
        {
            if (type.IsValueType)
                il.Emit(OpCodes.Unbox_Any, type);
            else
                il.Emit(OpCodes.Castclass, type);
        }
    }

}
